import {debounce} from 'lodash-es';
import {Formula} from "./FormulaUtil.js";
import CustomQuery from "./CustomQuery";
import loopControl from "./loopControl";
import Util from "@/js/Util.js"
import { Function } from "eval5";
export default {
    data(){
        return {
            Formula,
            calcWatchs:{}
        }
    },
    methods:{
        initFormConfig(callBack){
            //把容器中的组件循环出来
            if(this.metadataMobile.length === 0){ return }
            loopControl(this.metadataMobile,(item,type)=>{
                this.initFormula(item,type,item.field);
                this.initCustomQuery(item,type,item.field);
            })
            //挂载并监听公式 ;
            this.watchFormula()
            callBack()
        },
        /**
         * 初始化公式
         * @param config
         * @param type
         * @param tableName
         *
         * {
         *     表名1:{字段1:公式1,字段2:公式2}
         * }
         */
        initFormula(config,type,tableName){
            //main subTable oneTable
            if(type==="subTable"){
                if(!this.formulas[tableName]){
                    this.formulas[tableName]={};
                }
                let children={};
                /*
                * 没有考虑子表深层嵌套，已优化；
                * */
                let loopSubTableChildren = (list)=>{
                    for(let item of list){
                        if(item.children && item.children.length > 0){
                            loopSubTableChildren(item.children)
                        }
                        let controlConfig = item.controlConfig;
                        if(!controlConfig || !controlConfig.field){
                            continue;
                        }
                        let formulaValue= controlConfig.control?controlConfig.control.formulaValue:"";
                        if(!formulaValue){
                            continue;
                        }
                        let formulaCondition= controlConfig.control?controlConfig.control.formulaCondition:"";
                        children[controlConfig.field]={
                            calc:formulaValue,
                            condition:formulaCondition,
                        }
                    }
                }
                loopSubTableChildren(config.children);
                if(!this.formulas['subTable']){
                    this.formulas['subTable'] = {}
                }
                this.formulas['subTable'][tableName] = children;
            }else if(type==="oneTable"){
                if(!this.formulas[tableName]){
                    this.formulas[tableName]={};
                }
                let children={};
                //一对一子表里面有布局控件，嵌套多层的情况
                config.children.forEach(item=>{
                    loopControl(item.children,(item,type)=>{
                        if(item.control){
                            let {formulaValue,formulaCondition}= item.control;
                            if(formulaValue){
                                children[item.field]={
                                    calc:formulaValue,
                                    condition:formulaCondition,
                                };
                            }
                        }
                    })
                });
                if(!this.formulas['oneTable']){
                    this.formulas['oneTable'] = {}
                }
                this.formulas['oneTable'][tableName] = children;
            } else {
                let {formulaValue,formulaCondition} = config.control;
                if(!formulaValue){ return }
                if(!this.formulas[type]){
                    this.formulas[type]={};
                }
                this.formulas[type][config.field]={
                    calc:formulaValue,
                    condition:formulaCondition,
                };
            }
        },
        /**
         *<pre>
         * 初始化自定义查询.
         * </pre>
         * @param {string} config - 控件配置
         * @param {string} type - 当前控件所属表类型 主表为 main
         * @param {string} tableName - 当前控件所属表
         * @returns {Object} - 返回一个包含多个方法的对象
         */
        initCustomQuery(config,type,tableName){
            //main subTable oneTable
            if(type=="subTable"){
                if(!this.customQuery[tableName]){
                    this.customQuery[tableName]={};
                }
                let children={};
                for (let i = 0; i < config.children.length; i++) {
                    let controlConfig=config.children[i].controlConfig;
                    if(controlConfig && controlConfig.control && controlConfig.control.customQuery && controlConfig.control.customQuery.length>0){
                        children[controlConfig.field]=controlConfig.control.customQuery;
                    }
                }
                this.customQuery[tableName]=children;
            }else if(type=="oneTable"){
                if(!this.customQuery[tableName]){
                    this.customQuery[tableName]={};
                }
                let children={};
                let ary=this.getOneTableConfig(config);
                for (let i = 0; i < ary.length; i++) {
                    let control=ary[i];
                    let controlConfig=control.control;
                    if(controlConfig  && controlConfig.customQuery && controlConfig.customQuery.length>0){
                        children[control.field]=controlConfig.customQuery;
                    }
                }
                this.customQuery[tableName]=children;
            } else {
                if(config && config.control && config.control.customQuery && config.control.customQuery.length>0){
                    if(!this.customQuery[type]){
                        this.customQuery[type]={};
                    }
                    this.customQuery[type][config.field]=config.control.customQuery;
                }
            }
        },
        /**
         * 控件触发公共事件 处理公式、自定义查询
         * @param event 触发事件类型
         * @param value 字段值
         * @param key 字段标识
         * @param entName 表名 主表为main
         * @param data 表单数据
         */
        handlePublicEvent(event,value, key, entName,data){
            //判断是否存在entName
            if(!entName){
                return;
            }
            //处理自定义查询
            this.handleCustomQuery(entName, key, data,event);
        },
        /**
         * <pre>
         * 处理自定义查询
         * </pre>
         * @param {String} tableName -当前表 主表main
         * @param {String} field -当前控件字段名
         * @param {Object} data  -表数据
         * @param {String} event -触发的事件
         * @returns
         */
        handleCustomQuery(tableName, field, data,event) {
            if(this.customQuery && this.customQuery[tableName]){
                let queryList=this.customQuery[tableName][field]
                if(queryList && queryList.length>0){
                    for (let i = 0; i < queryList.length; i++) {
                        let events=queryList[i].event;
                        //判断是否执行
                        let isExecute = events.includes(event);
                        if(isExecute){
                            CustomQuery.executeCustomQuery(queryList[i],data,tableName,this.data,this);
                        }
                    }
                }
            }
        },
        /**
         * 新增、编辑、明细时
         * 执行自定义查询.
         */
        executeCustomQuery(){
            if(!this.customQuery){
                return;
            }
            let event="";
            //判断当前触发的事件
            if (this.readOnly) {
                event = "detailInit";
            } else {
                if (this.data.ID_) {
                    event = "editInit";
                } else {
                    event = "addInit";
                }
            }
            for (let tableName in this.customQuery){
                let fieldObj=this.customQuery[tableName];
                for (let field in fieldObj){
                    //执行自定义查询
                    this.handleCustomQuery(tableName, field, this.data,event);
                }
            }
        },
        /**
         * 获取一对一子表的字段组件
         * @param config 一对一的配置
         * @returns {*[]}
         */
        getOneTableConfig(config){
            let ary=[];
            let loopCtl = (config)=>{
                loopControl(config,(item)=>{
                    ary.push(item);
                })
            }
            config.children.forEach(col=>{
                if(col.children){
                    loopCtl(col.children)
                }
            })
            return ary;
        },
        /**
         * 获取当前挂载的监听的缓存节点
         * @param key 控件的字段
         * @param type 主表/子表/一对一子表
         * @param tableKey 子表字段/一对一子表字段
         * @returns {*}
         */
        getCalcWatch(key,type,tableKey,row){
            if(tableKey){
                let rowKey =row?  row.index_ || row.idx_  : '';
                let _key = '';
                if(rowKey){//子表
                    _key = `${type}_${tableKey}_${rowKey}_${key}` ;
                    if(!this.calcWatchs[_key]){
                        this.calcWatchs[_key] = {}
                    }
                }else if(!this.calcWatchs[`${type}_${tableKey}_${key}`]){
                    _key = `${type}_${tableKey}_${key}`
                    this.calcWatchs[_key] = {}
                }
                return this.calcWatchs[_key] ;
            }else {
                if(!this.calcWatchs[`${type}_${key}`]){
                    this.calcWatchs[`${type}_${key}`] = {}
                }
                return  this.calcWatchs[`${type}_${key}`]
            }
        },
        /*
        * 删除当前子表控件的行监听
        * row:要删除的行数据
        * subKey:子表的key
        * */
        delSubTableRowWatch(row){
            let rowKey =row?  row._key || row.idx_  : '';
            let subRowKey = `subTable_${rowKey}`
            let rowWatchKey = Object.keys(this.calcWatchs).filter(o=>o.includes(subRowKey));
            for(let item of rowWatchKey){
                this.calcWatchs[item].calc && this.calcWatchs[item].calc();
                this.calcWatchs[item].condition && this.calcWatchs[item].condition();
                Reflect.deleteProperty(this.calcWatchs,item)
            }
        },
        /**
         * 为字段设置监听器
         * @param calc 自定义公式
         * @param key  挂载公式的控件的字段
         * @param type 控件所属，主表/子表/一对一子表
         * @param tableKey 子表/一对一子表的字段
         * @param idx 子表中行的下标
         * @param row 子表中一行的值
         */
        ctlWatch(calc,key,type,tableKey,idx,row){
            /*控件自定义公式 监听 挂载*/
            if(!calc.includes('return')){
                calc = `return ${calc}`
            }
            let calcWatch = this.getCalcWatch(key,type,tableKey,row);
            try {
                calcWatch.calc = this.$watch(()=>{
                    if(idx === undefined){ idx = 0}
                    if(row === undefined){ row = {}}
                    return new Function('data','Formula','rowIndex','row',calc).call(this,this.data,this.Formula,idx,row) ;
                },(v)=>{
                    if(typeof v !=="boolean" && v !== 0 && !v){
                        v =''
                    }
                    //获取当前控件配置
                    let config = this.getConfigByField(tableKey,key,this.metadataMobile);
                    if(type === 'subTable'){
                        config=config.controlConfig;
                    }
                    //数字控件
                    if(config.type === "number" && v){
                        v = Util.roundToPrecision(v,config.options.decimalLength || 0)
                    }else {
                        v = v + '';
                    }
                    if(type === 'oneTable'){
                        this.data[`sub__${tableKey}`][key] = v ;
                    }else if(type === 'subTable'){
                        this.data[`sub__${tableKey}`][idx][key] = v ;
                    } else {
                        this.data[key] = v ;
                    }
                },{deep:true,immediate:true})
            }catch (e) {
                console.log('计算公式配错了！')
            }
        },
        /**
         * 当自定义公式有条件的时候挂载控件监听
         * @param calcConfig 当前控件的自定义公式
         * @param key 配置了公式的控件的字段
         * @param type 控件所属，主表/子表/一对一子表
         * @param tableKey 子表/一对一子表的字段
         * @param idx 子表中行的下标
         * @param row 子表中一行的值
         */
        conditionWatch(calcConfig,key,type,tableKey,idx,row){
            let {condition,calc} = calcConfig ;
            /*判断是否满足条件*/
            if(!condition.includes('return')){
                condition = `return ${condition}`
            }
            let calcWatch = this.getCalcWatch(key,type,tableKey,row);
            try {
                calcWatch.condition = this.$watch(()=>{
                    if(idx === undefined){ idx = 0}
                    if(row === undefined){ row = {}}
                    return new Function('data','Formula','rowIndex','row',condition).call(this,this.data,this.Formula,idx,row)
                },(v)=>{
                    if(v){//条件为真时，挂载监听
                        this.ctlWatch(calc,key,type,tableKey,idx)
                    }else {//条件为假时，卸载监听
                        calcWatch && calcWatch.calc && calcWatch.calc()
                    }
                },{deep:true,immediate:true})
            }catch (e) {
                // console.log('计算公式配错了！')
            }
        },
        /**
         *
         * @param calcObj 当前表单的自定义字段合集
         * @param type 主表（main） 一对一子表（oneTable） 子表(subTable)
         * @param tableKey 子表或者一对一子表的字段
         */
        watchControl(calcObj,type,tableKey,idx,row){
            /*挂载主表自定义公式的 数据监听*/
            if(calcObj && Object.keys(calcObj).length === 0){ return }
            for (let key in calcObj){
                let {calc,condition} = calcObj[key];
                if(!calc){ continue }
                if(condition){//有条件时
                    this.conditionWatch(calcObj[key],key,type,tableKey,idx,row);
                }else {//没有条件时
                    this.ctlWatch(calc,key,type,tableKey,idx,row)
                }
            }
        },
        /**
         * 一对一子表控件公式挂载
         * @param calcObj 一对一子表里面控件自定义公式的合集
         */
        watchOneTable(calcObj){
            /*一对一子表*/
            for(let oneTableKey in calcObj){
                let oneTable = calcObj[oneTableKey]
                this.watchControl(oneTable,'oneTable',oneTableKey)
            }
        },

        /**
         * 子表控件公式挂载
         * @param calcObj 子表里面控件自定义公式的合集
         * calcObj:{
         *     subTableField1:{
         *         columnField:{
         *             calc:'',
         *             condition:''
         *         }
         *     },
         *     ......
         * }
         *
         */
        watchSubTable(calcObj){
            /*子表*/
            for(let subTableKey in calcObj){
                let subTable = calcObj[subTableKey] ;
                this.$watch(()=>{
                    return this.data[`sub__${subTableKey}`]
                },(val)=>{
                    if(!val){
                        return
                    }
                    for(let item of Object.keys(this.calcWatchs)){
                        if(item.includes(`subTable_${subTableKey}`)){
                            this.calcWatchs[item].calc && this.calcWatchs[item].calc();
                            this.calcWatchs[item].condition && this.calcWatchs[item].condition();
                            Reflect.deleteProperty(this.calcWatchs,item)
                        }
                    }
                    for (let idx = 0 ; idx < val.length;idx++){
                        this.watchControl(subTable,'subTable',subTableKey,idx,val[idx])
                    }
                },{deep:true})
            }
        },
        watchFormula(){
            let { formulas } = this ;
            for (let key in formulas){
                if(key === 'main'){
                    /*主表*/
                    this.watchControl(formulas[key],key)
                }else if(key === 'oneTable'){
                    /*一对一子表*/
                    this.watchOneTable(formulas[key])
                }else if(key === 'subTable'){
                    /*一对多子表*/
                    this.watchSubTable(formulas[key])
                }
            }
        },
        /**
         * 根据field获取当前控件配置
         * @param table
         * @param field
         * @param formConfig
         */
        getConfigByField(table, field, formConfig){
            let config = "";
            loopControl(formConfig, (item, type) => {
                if ((type=="subTable" || type=="oneTable") && item.field == table) {
                    config = this.getConfigByField(item.field,field,item.children);
                    if(config){
                        return true;
                    }
                }  else {
                    if(item.field == field){
                        config = item;
                        return true;
                    }
                }
            })
            return config;
        }
    }
}
